/*
 * HexBase.java
 *
 * Created on November 15, 2007, 7:31 PM
 *
 * Copyright (C) 2007-2008  Hylke van der Schaaf
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, in version 3 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

package hextd.hex;

import hextd.hex.Hex.highlightType;
import hextd.tower.Tower;
import hextd.util.Context;
import hextd.util.Geometry;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.Line2D;
import java.util.Vector;

/**
 *
 * @author hylke
 */
public class HexBase implements  Hex {
    protected char shortName;
    protected int type;
    protected int x;
    protected int y;
    
    protected float paintScale;
    protected float xFloat,yFloat;
    protected float xPaint,yPaint;
    protected float wFloat,hFloat;
    protected float wPaint,hPaint;
    
    private float[][] points;
    
    protected GeneralPath polyHex;
    protected Stroke stroke1;
    protected Stroke stroke2;
    protected Shape[] bordersE;
    protected Color borderColor;
    protected Color borderEmptyColor;
    protected Color fillColor;
    protected Color highlightOK;
    protected Color highlightNOK;
    private   Color rangeColor;
    
    protected Context       context;
    protected highlightType highlight = highlightType.none;
    private   float         highlightRange=0;
    private   Shape         rangeCircle;
    
    private   boolean       free = true;
    private   Tower         tower = null;
    
    /** Creates a new instance of HexBase */
    public HexBase(int x, int y, Context context, boolean buildable) {
        Color tempColor;
        // even or odd
        this.x = x;
        this.y = y;
        this.context = context;
        this.borderColor = this.context.colors.getColorBaseHexBorder();
        
        tempColor  = this.context.colors.getColorBaseHexBackGround();
        this.fillColor = new Color(tempColor.getRed(), tempColor.getGreen(), tempColor.getBlue(), 125);
        this.borderEmptyColor = this.context.colors.getColorBaseEmptyHexBorder();
        tempColor = this.context.colors.getColorHighlightOK();
        this.highlightOK = new Color(tempColor.getRed(), tempColor.getGreen(), tempColor.getBlue(), 125);
        tempColor = this.context.colors.getColorHighlightNOK();
        this.highlightNOK = new Color(tempColor.getRed(), tempColor.getGreen(), tempColor.getBlue(), 125);
        this.rangeColor = this.context.colors.getColorRangeCircle();
        this.type = Hex.BASE;
        this.shortName = 'b';
        this.free = buildable;
    }
    
    public void setLocation(int x, int y) {
        this.x = x;
        this.y = y;
    }
    
    public int[] getLocation() {
        int[] retVal = new int[2];
        retVal[0] = this.x;
        retVal[1] = this.y;
        return retVal;
    }
    
    public float[] getFloatLocation() {
        float[] returnVal = new float[2];
        returnVal[0] = this.xFloat;
        returnVal[1] = this.yFloat;
        return returnVal;
    }
    public float[] getPaintLocation() {
        float[] returnVal = new float[2];
        returnVal[0] = this.xPaint;
        returnVal[1] = this.yPaint;
        return returnVal;
    }
    
    public boolean hasTower() {
        return (this.tower != null);
    }
    
    public void unSetTower() {
        if (this.tower != null) {
            this.tower = null;
            this.free = true;
        }
    }
    public void setTower(Tower tower) {
        if (this.free) {
            this.tower = tower;
            this.free = false;
        }
    }
    
    public Tower getTower() {
        return this.tower;
    }
    
    
    public void setHighlight(highlightType highlight) {
        this.highlight = highlight;
    }
    
    public void setHighlightRange(float range) {
        this.highlightRange = range;
        float paintRange = this.highlightRange * this.paintScale;
        float xPaint = this.context.offsetX + this.xFloat * this.paintScale;
        float yPaint = this.context.offsetY + this.yFloat * this.paintScale;
        this.rangeCircle = new Ellipse2D.Float(xPaint-paintRange, yPaint-paintRange, paintRange*2, paintRange*2);
    }
    
    public void resetScale() {
        this.paintScale = this.context.paintScale;
        float paintX, paintY;
        
        int shift = this.y&1;
        this.wFloat = (float)Math.sin(Math.PI/3);
        this.xFloat = this.wFloat + this.x*this.wFloat*2 + shift*this.wFloat;
        this.yFloat = 1.5f*this.y + 1;
        
        this.wPaint = this.wFloat * this.paintScale;
        this.xPaint = this.context.offsetX + this.xFloat * this.paintScale;
        this.yPaint = this.context.offsetY + this.yFloat * this.paintScale;
        
        this.points = Geometry.createPolyCoords(this.paintScale, xPaint, yPaint);
        this.polyHex = Geometry.coordsToGeneralPath(this.points, true);
        
        Vector<Shape> borders = new Vector<Shape>();
        Hex[][] grid = this.context.grid;
        if ( this.x < (this.context.gridWidth-(this.y&1)-1) && grid[this.x+1][this.y].getType() == Hex.PATH) {
            // Right is empty
            Line2D tempLine = new Line2D.Float(xPaint+this.wPaint, yPaint-paintScale/2, xPaint+this.wPaint, yPaint+paintScale/2);
            borders.add(tempLine);
        }
        if ( this.y > 0 && this.x+(this.y&1) <= (this.context.gridWidth-((this.y-1)&1)-1) && (grid[this.x+(this.y&1)][this.y-1].getType() == Hex.PATH) ) {
            // Right-Up is empty
            Line2D tempLine = new Line2D.Float(xPaint+0, yPaint-paintScale, xPaint+this.wPaint, yPaint-paintScale/2);
            borders.add(tempLine);
        }
        
        if ( this.y < this.context.gridHeight-1 && this.x+(this.y&1) <= (this.context.gridWidth-((this.y+1)&1)-1) && (grid[this.x+(this.y&1)][this.y+1].getType() == Hex.PATH) ) {
            // Right-Down is empty
            Line2D tempLine = new Line2D.Float(xPaint+0, yPaint+paintScale, xPaint+this.wPaint, yPaint+paintScale/2);
            borders.add(tempLine);
        }
        
        
        if ( (this.x > 0) && (grid[this.x-1][this.y].getType() == Hex.PATH) ) {
            // Left is empty
            Line2D tempLine = new Line2D.Float(xPaint-this.wPaint, yPaint-paintScale/2, xPaint-this.wPaint, yPaint+paintScale/2);
            borders.add(tempLine);
        }
        
        if ( this.y > 0 && this.x-((this.y+1)&1) >= 0 && (grid[this.x-((this.y+1)&1)][this.y-1].getType() == Hex.PATH) ) {
            // Left-Up is empty
            Line2D tempLine = new Line2D.Float(xPaint+0, yPaint-paintScale, xPaint-this.wPaint, yPaint-paintScale/2);
            borders.add(tempLine);
        }
        if ( this.y < this.context.gridHeight-1 && this.x-((this.y+1)&1) >= 0 && (grid[this.x-((this.y+1)&1)][this.y+1].getType() == Hex.PATH) ) {
            // Left-Down is empty
            Line2D tempLine = new Line2D.Float(xPaint+0, yPaint+paintScale, xPaint-this.wPaint, yPaint+paintScale/2);
            borders.add(tempLine);
        }
        
        this.bordersE = new Shape[borders.size()];
        this.bordersE = borders.toArray(this.bordersE);
        
        this.stroke1 = new BasicStroke(1.0f*this.context.strokeScale, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL);
        this.stroke2 = new BasicStroke(3.0f*this.context.strokeScale, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
        
        float paintRange = this.highlightRange * this.paintScale;
        this.rangeCircle = new Ellipse2D.Float(xPaint-paintRange, yPaint-paintRange, paintRange*2, paintRange*2);
    }
    
    public void paintRangeCircle(Graphics2D g2) {
        g2.setColor(this.rangeColor);
        g2.draw(this.rangeCircle);
    }
    
    public void paintBase(Graphics2D g2_0, Graphics2D g2_1) {
        if (g2_1 != null) {
            Stroke defaultStroke = g2_1.getStroke();
            
            g2_1.setStroke(this.stroke1);
            g2_1.setColor(this.fillColor);
            g2_1.fill(this.polyHex);
            g2_1.setColor(this.borderColor);
            g2_1.draw(this.polyHex);
            
            g2_1.setStroke(this.stroke2);
            g2_1.setColor(this.borderEmptyColor);
            for (int i=0; i<this.bordersE.length; i++) {
                g2_1.draw(this.bordersE[i]);
            }
            
            g2_1.setStroke(defaultStroke);
        }
    }
    
    public void paintEffects(Graphics2D g2) {
        switch (this.highlight) {
            case placeTower:
                if (this.free) {
                    g2.setColor(this.highlightOK);
                    this.paintRangeCircle(g2);
                } else {
                    g2.setColor(this.highlightNOK);
                    this.paintRangeCircle(g2);
                }
                g2.fill(this.polyHex);
                break;
            case editHex:
                g2.setColor(this.highlightOK);
                g2.fill(this.polyHex);
                break;
            case selectTower:
                g2.setColor(this.highlightOK);
                g2.fill(this.polyHex);
                break;
        }
    }
    
    public char getShortName() {
        return this.shortName;
    }
    
    public int getType() {
        return type;
    }
    
    public boolean isFree() {
        return free;
    }
    
}
